import threading
import time
from enum import Enum
import random
from datetime import datetime

# 电梯状态枚举
class ElevatorStatus(Enum):
    IDLE = "空闲"
    MOVING_UP = "向上运行"
    MOVING_DOWN = "向下运行"
    DOOR_OPEN = "门打开"
    DOOR_CLOSED = "门关闭"


# 电梯类
class Elevator:
    def __init__(self, elevator_id):
        self.id = elevator_id
        self.current_floor = 1  # 起始楼层
        self.target_floors = set()  # 目标楼层集合
        self.status = ElevatorStatus.IDLE  # 当前状态
        self.direction = None  # 运行方向，None表示无方向
        self.max_floor = 3  # 最大楼层
        self.min_floor = 1  # 最小楼层
        self.passengers = 0  # 乘客数量
        self.max_passengers = 8  # 最大载客量
        self.is_running = True  # 电梯是否运行
        self.last_activity = datetime.now()  # 最后活动时间

        # 启动电梯控制线程
        self.thread = threading.Thread(target=self.run, daemon=True)
        self.thread.start()

    def add_target(self, floor):
        """添加目标楼层"""
        if self.min_floor <= floor <= self.max_floor:
            self.target_floors.add(floor)
            self.last_activity = datetime.now()
            return True
        return False

    def remove_target(self, floor):
        """移除目标楼层"""
        if floor in self.target_floors:
            self.target_floors.remove(floor)
            return True
        return False

    def open_door(self):
        """开门"""
        
        time.sleep(5)  # 门打开需要时间
        self.status = ElevatorStatus.DOOR_OPEN

    def close_door(self):
        """关门"""
        
        time.sleep(5)  # 门关闭需要时间
        self.status = ElevatorStatus.DOOR_CLOSED

    def move_to_next_floor(self):
        """移动到下一楼层"""
        if not self.target_floors:
            self.status = ElevatorStatus.IDLE
            self.direction = None
            return

        # 确定运行方向
        if self.direction is None:
            # 没有方向时，选择最近的目标楼层
            targets = sorted(self.target_floors)
            if self.current_floor in targets:
                self.target_floors.remove(self.current_floor)
                return

            above = [f for f in targets if f > self.current_floor]
            below = [f for f in targets if f < self.current_floor]

            if above and (not below or above[0] - self.current_floor <= self.current_floor - below[-1]):
                self.direction = ElevatorStatus.MOVING_UP
            else:
                self.direction = ElevatorStatus.MOVING_DOWN

        # 根据方向移动
        if self.direction == ElevatorStatus.MOVING_UP:
            self.status = ElevatorStatus.MOVING_UP
            next_floor = self.current_floor + 1
            if next_floor > self.max_floor:
                self.direction = ElevatorStatus.MOVING_DOWN
                next_floor = self.current_floor - 1
        else:
            self.status = ElevatorStatus.MOVING_DOWN
            next_floor = self.current_floor - 1
            if next_floor < self.min_floor:
                self.direction = ElevatorStatus.MOVING_UP
                next_floor = self.current_floor + 1

        # 移动到下一楼层
        time.sleep(1)  # 模拟移动时间
        self.current_floor = next_floor
        self.last_activity = datetime.now()

        # 检查是否到达目标楼层
        if self.current_floor in self.target_floors:
            self.target_floors.remove(self.current_floor)
            self.stop_at_floor()

    def stop_at_floor(self):
        """在楼层停下"""
        self.status = ElevatorStatus.IDLE
        self.open_door()

        # 模拟乘客上下
        self.passengers = max(0, min(self.max_passengers, self.passengers + random.randint(-2, 3)))

        self.close_door()

        # 如果没有目标了，更新状态
        if not self.target_floors:
            self.direction = None

    def run(self):
        """电梯运行主循环"""
        while self.is_running:
            if self.target_floors:
                self.move_to_next_floor()
            else:
                # 空闲状态，每5秒检查一次
                time.sleep(5)

    def get_status(self):
        """获取电梯当前状态"""
        return {
            "id": self.id,
            "current_floor": self.current_floor,
            "target_floors": sorted(self.target_floors),
            "status": self.status.value,
            "direction": self.direction.value if self.direction else None,
            "passengers": self.passengers,
            "max_passengers": self.max_passengers,
            "last_activity": self.last_activity.strftime("%Y-%m-%d %H:%M:%S")
        }

    def stop(self):
        """停止电梯运行"""
        self.is_running = False
        self.thread.join()


# 电梯系统管理类
class ElevatorSystem:
    def __init__(self, num_elevators=2):
        self.elevators = [Elevator(i + 1) for i in range(num_elevators)]
        self.requests = []  # 外部请求
        self.is_running = True

        # 启动请求处理线程
        self.thread = threading.Thread(target=self.process_requests, daemon=True)
        self.thread.start()

    def add_request(self, floor, direction=None):
        """添加外部请求"""
        self.requests.append((floor, direction))

    def process_requests(self):
        """处理外部请求，分配给最合适的电梯"""
        while self.is_running:
            if self.requests:
                floor, direction = self.requests.pop(0)

                # 找到最合适的电梯
                best_elevator = None
                best_score = float('inf')

                for elevator in self.elevators:
                    # 简单的评分机制：距离 + 方向因素
                    distance = abs(elevator.current_floor - floor)

                    # 方向因素：同方向或空闲的电梯加分
                    direction_factor = 0
                    if elevator.direction:
                        if (
                                direction == "up" and elevator.direction == ElevatorStatus.MOVING_UP and floor > elevator.current_floor) or \
                                (
                                        direction == "down" and elevator.direction == ElevatorStatus.MOVING_DOWN and floor < elevator.current_floor):
                            direction_factor = -2  # 同方向加分
                        else:
                            direction_factor = 2  # 反方向减分

                    score = distance + direction_factor

                    if score < best_score:
                        best_score = score
                        best_elevator = elevator

                if best_elevator:
                    best_elevator.add_target(floor)

            time.sleep(1)  # 每秒检查一次请求

    def get_all_statuses(self):
        """获取所有电梯的状态"""
        return [elevator.get_status() for elevator in self.elevators]

    def stop(self):
        """停止系统"""
        self.is_running = False
        self.thread.join()
        for elevator in self.elevators:
            elevator.stop()